﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO.IsolatedStorage;
using System.Windows.Media.Imaging;
using System.IO;
using System.Runtime.Serialization;
using PhotoUploader.Models;
using System.Collections.Generic;
using PhotoUploader.Common;
using System.Linq;
using Microsoft.Phone.BackgroundTransfer;

namespace PhotoUploader.Services
{
    public class PictureRepository
    {
        #region Constants

        public const string IsolatedStoragePath = "Pictures";

        #endregion        

        #region Fields

        private ObservableCollection<Picture> _pictures = new ObservableCollection<Picture>();

        #endregion

        #region Properties

        public ObservableCollection<Picture> Pictures
        {
            get { return _pictures; }
        }

        #endregion

        #region Operations

        public Picture LoadFromLocalStorage(string fileName, string directory)
        {
            var isoFile = IsolatedStorageFile.GetUserStoreForApplication();

            string filePath = Path.Combine(directory, fileName);
            if (isoFile.FileExists(filePath) == false) return null;
            using (var fileStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new BinaryReader(fileStream))
                {
                    var picture = new Picture();
                    picture.Deserialize(reader);
                    return picture;
                }
            }
        }

        public Picture GetPicture(string fileName)
        {
            var picture = Pictures.Where(p => p.FileName == fileName).FirstOrDefault();

            if (picture != null)
            {
                return picture;
            }
            else
            {
                picture = LoadFromLocalStorage(fileName, IsolatedStoragePath);                
                return picture;
            }
        }

        public void SaveToLocalStorage(Picture picture, string directory)
        {
            var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
            isoFile.EnsureDirectory(directory);

            string filePath = Path.Combine(directory, picture.FileName);
            using (var fileStream = isoFile.CreateFile(filePath))
            {
                using (var writer = new BinaryWriter(fileStream))
                {
                    picture.Serialize(writer);
                }
            }
        }

        public void SavePicture(Picture picture)
        {
            if (!Pictures.Contains(picture))
                Pictures.Add(picture);
            SaveToLocalStorage(picture, IsolatedStoragePath);
        }

        public void RemoveFromLocalStorage(Picture picture, string directory)
        {
            var isoFile = IsolatedStorageFile.GetUserStoreForApplication();

            string filePath = Path.Combine(directory, picture.FileName);
            if (isoFile.FileExists(filePath))
                isoFile.DeleteFile(filePath);
        }

        public void RemovePicture(Picture picture)
        {
            Pictures.Remove(picture);
            RemoveFromLocalStorage(picture, IsolatedStoragePath);
        }

        private IEnumerable<Picture> GetAllPicturesFromIsolatedStorage()
        {
            var pictures = new List<Picture>();

            var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
            isoFile.EnsureDirectory(IsolatedStoragePath);

            var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg"));
            foreach (var pictureFile in pictureFiles)
            {
                var picture = LoadFromLocalStorage(pictureFile, IsolatedStoragePath);
                if (pictureFile.Contains("WideShot"))
                {
                    picture.NickName = "整体损坏照片";
                }
                if (pictureFile.Contains("DetailPhoto1"))
                {
                    picture.NickName = "局部照片1";
                }
                if (pictureFile.Contains("DetailPhoto2"))
                {
                    picture.NickName = "局部照片2";
                }
                pictures.Add(picture);
            }

            return pictures;
        }

        public void LoadAllPicturesFromIsolatedStorage()
        {
            var pictures = GetAllPicturesFromIsolatedStorage();

            LoadAllPictures(pictures);
        }

        public void LoadAllPictures(IEnumerable<Picture> pictures)
        {
            _pictures.Clear();

            foreach (var picture in pictures)
            {                
                _pictures.Add(picture);
            }
        }

        #endregion

        #region Singleton Pattern

        public static readonly PictureRepository Instance = new PictureRepository();

        #endregion

    }

    public static class PictureRepositoryExtensions
    {
        public static void SetPictureStatus(this PictureRepository pictureRepository, string fileName, FileStatus fileStatus, string requestId)
        {
            var picture = pictureRepository.FindPictureWithFileName(fileName);
            if (picture == null) return;

            pictureRepository.SetPictureStatus(picture, fileStatus, picture.RequestId);
        }

        public static void SetPictureStatus(this PictureRepository pictureRepository, string requestId, FileStatus fileStatus)
        {
            var picture = pictureRepository.FindPictureWithRequestId(requestId);
            if (picture == null) return;

            pictureRepository.SetPictureStatus(picture, fileStatus, picture.RequestId);
        }

        public static void SetPictureStatus(this PictureRepository pictureRepository, Picture picture, FileStatus fileStatus, string requestId)
        {
            picture.FileStatus = fileStatus;
            picture.RequestId = (fileStatus == FileStatus.Active) ? requestId : null;

            switch (fileStatus)
            {
                case FileStatus.New:
                    picture.TransferStatus = TransferStatus.None;
                    break;
            }
            pictureRepository.SavePicture(picture);
        }
        public static void UpdatePicture(this PictureRepository pictureRepository, string requestId, TransferStatus transferStatus, long bytesSent, long totalBytesToSend)
        {
            var picture = pictureRepository.FindPictureWithRequestId(requestId);
            if (picture == null) return;

            picture.TransferStatus = transferStatus;
            picture.BytesSent = bytesSent;
            picture.TotalBytesToSend = totalBytesToSend;
        }

        public static void RemovePicture(this PictureRepository pictureRepository, string requestId)
        {
            var picture = pictureRepository.FindPictureWithRequestId(requestId);
            if (picture == null) return;

            pictureRepository.RemovePicture(picture);
        }

        public static Picture FindPictureWithRequestId(this PictureRepository pictureRepository, string requestId)
        {
            return pictureRepository.Pictures.Where(p => p.RequestId == requestId).FirstOrDefault();
        }

        public static Picture FindPictureWithFileName(this PictureRepository pictureRepository, string fileName)
        {
            return pictureRepository.Pictures.Where(p => p.FileName == fileName).FirstOrDefault();
        }
    }
}
